﻿using System;
using Nop.Core.Domain.Orders;
using Nop.Core.Plugins;
using Nop.Services.Events;
using Nop.Services.Orders;
using System.Net;
using System.IO;
using System.Text;
using System.Web;
using System.Linq;
using Nop.Services.Logging;
using System.Globalization;
using Nop.Services.Common;
using Nop.Core.Domain.Customers;
using Nop.Services.Messages;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using Nop.Services.Stores;
using Nop.Core;
using Nop.Services.Configuration;
using Nop.Core.Domain.Messages;
using Nop.Core.Domain.Shipping;
using Nop.Core.Infrastructure;
using Nop.Core.Data;
using System.Data.Entity;
using Nop.Data;
using System.Data.Entity.Infrastructure;
using Nop.Services.Localization;

namespace Nop.Plugin.Widgets.EKomi
{
    public class EventConsumer : IConsumer<MessageTokensAddedEvent<Token>>, IConsumer<EntityTokensAddedEvent<Shipment, Token>>
    {
        private readonly IWorkContext _workContext;
        private readonly IStoreContext _storeContext;
        private readonly IStoreService _storeService;
        private readonly HttpContextBase _httpContext;
        private readonly EKomiSettings _eKomiSettings;
        private readonly IWebHelper _webHelper;
        private readonly ISettingService _settingService;
        private readonly IOrderService _orderService;
        private readonly ILogger _logger;
        private readonly INewsLetterSubscriptionService _newsLetterSubscriptionService;
        private readonly ILanguageService _languageService;

        private readonly CultureInfo _usCulture;
        private Shipment shipment;

        public EventConsumer(IWorkContext workContext,
           IStoreContext storeContext, IStoreService storeService,
            HttpContextBase httpContext,
            IWebHelper webHelper,
            ISettingService settingService,
            IOrderService orderService,
            INewsLetterSubscriptionService newsLetterSubscriptionService,
            ILanguageService languageService,
            ILogger logger)
        {
            this._workContext = workContext;
            this._storeContext = storeContext;
            this._storeService = storeService;
            this._httpContext = httpContext;
            this._webHelper = webHelper;
            this._settingService = settingService;
            this._orderService = orderService;
            this._logger = logger;
            this._newsLetterSubscriptionService = newsLetterSubscriptionService;
            this._languageService = languageService;
            this._usCulture = new CultureInfo("en-US");

            //load settings for a chosen store scope
            var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext);
            _eKomiSettings = _settingService.LoadSetting<EKomiSettings>(storeScope);

        }

        public virtual int GetActiveStoreScopeConfiguration(IStoreService storeService, IWorkContext workContext)
        {
            //ensure that we have 2 (or more) stores
            if (storeService.GetAllStores().Count < 2)
                return 0;

            var storeId = workContext.CurrentCustomer.GetAttribute<int>(SystemCustomerAttributeNames.AdminAreaStoreScopeConfiguration);
            var store = storeService.GetStoreById(storeId);
            return store != null ? store.Id : 0;
        }

        /// <summary>
        /// Called fisrt
        /// </summary>
        /// <param name="eventMessage"></param>
        void IConsumer<EntityTokensAddedEvent<Shipment, Token>>.HandleEvent(EntityTokensAddedEvent<Shipment, Token> eventMessage)
        {
            shipment = eventMessage.Entity;
        }


        /// <summary>
        /// Handles the event.
        /// </summary>
        /// <param name="eventMessage">The event message.</param>
        void IConsumer<MessageTokensAddedEvent<Token>>.HandleEvent(MessageTokensAddedEvent<Token> eventMessage)
        {
            try
            {
                if (shipment != null && eventMessage.Message.Name == "ShipmentSent.CustomerNotification")
                {
                    bool exclusion = false;

                    var skus = _eKomiSettings.NoFeedbackForTheseSku.Split(';');

                    foreach (var orderItem in shipment.Order.OrderItems)
                    {
                        foreach (var sku in skus)
                        {
                            if (orderItem.Product.Sku == sku)
                            {
                                exclusion = true;
                                break;
                            }
                        }
                        if (exclusion)
                            break;
                    }

                    //Points relais
                    if (shipment.Order.ShippingMethod.Contains("["))
                    {
                        exclusion = true;
                    }

                    if (_eKomiSettings.SendMailToEKomi && !exclusion)
                    {
                        SendShipmentSentEKomiNotification(shipment);
                    }

                }

            }
            catch (System.Exception ex)
            {
                _logger.Error("eKomi check NoFeedbackForTheseSku error", ex);
            }

        }


        public virtual void SendShipmentSentEKomiNotification(Shipment shipment)
        {
            var store = _storeService.GetStoreById(shipment.Order.StoreId) ?? _storeContext.CurrentStore;

            //load any language from the specified store
            int languageId = _languageService.GetAllLanguages(storeId: store.Id).FirstOrDefault().Id;


            var _tokenizer = EngineContext.Current.Resolve<ITokenizer>();
            var _emailAccountService = EngineContext.Current.Resolve<IEmailAccountService>();
            var _messageTokenProvider = EngineContext.Current.Resolve<IMessageTokenProvider>();
            var _queuedEmailService = EngineContext.Current.Resolve<IQueuedEmailService>();
            var _emailAccountSettings = EngineContext.Current.Resolve<EmailAccountSettings>();
            var emailAccount = _emailAccountService.GetEmailAccountById(_emailAccountSettings.DefaultEmailAccountId);
            if (emailAccount == null)
                emailAccount = _emailAccountService.GetAllEmailAccounts().FirstOrDefault();
            
            //tokens
            var tokens = new List<Token>();
            _messageTokenProvider.AddStoreTokens(tokens, store, emailAccount);
            _messageTokenProvider.AddShipmentTokens(tokens, shipment, languageId);
            _messageTokenProvider.AddOrderTokens(tokens, shipment.Order, languageId);
            _messageTokenProvider.AddCustomerTokens(tokens, shipment.Order.Customer);


            //Replace subject and body tokens 
            var subjectReplaced = _tokenizer.Replace(_eKomiSettings.Subject, tokens, false);
            var bodyReplaced = _tokenizer.Replace(_eKomiSettings.Body, tokens, true);

            var email = new QueuedEmail()
            {
                Priority = 5,
                From = emailAccount.Email,
                FromName = emailAccount.DisplayName,
                To = _eKomiSettings.Email,
                ToName = "eKomi feebback service",
                CC = string.Empty,
                Bcc = string.Empty,
                Subject = subjectReplaced,
                Body = bodyReplaced,
                AttachmentFilePath = string.Empty,
                AttachmentFileName = string.Empty,
                CreatedOnUtc = DateTime.UtcNow,
                EmailAccountId = emailAccount.Id
            };

            _queuedEmailService.InsertQueuedEmail(email);
        
        }






    }
}